/**
Copyright [2008] [Julian Gamble] 

Licensed under the Apache License, Version 2.0 (the "License"); 
you may not use this file except in compliance with the License. 
You may obtain a copy of the License at 

	http://www.apache.org/licenses/LICENSE-2.0 
	
Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
See the License for the specific language governing permissions and 
limitations under the License. 
 **/
package aerith.components;

import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JMenuBar;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputListener;

public class AerithTitleBar extends JMenuBar {

	private static final long serialVersionUID = -5447512110890950725L;
	private JButton closeButton;
	private JButton iconifyButton;

	////////////////////////////////////////////////////////////////////////////
	// THEME SPECIFIC FIELDS
	////////////////////////////////////////////////////////////////////////////

	private int preferredHeight = 20;

	private Color lightColor = Color.decode("#4B5461");

	private Color shadowColor = Color.decode("#202737");

	private BufferedImage grip;

	private BufferedImage backgroundGradient;

	private Color inactiveLightColor;

	private Color inactiveShadowColor;

	private BufferedImage inactiveGrip;

	private BufferedImage inactiveBackgroundGradient;

	private BufferedImage close;

	private BufferedImage closeInactive;

	private BufferedImage closeOver;

	private BufferedImage closePressed;
	//@InjectedResource
	private BufferedImage minimize;

	private BufferedImage minimizeInactive;

	private BufferedImage minimizeOver;

	private BufferedImage minimizePressed;

	public AerithTitleBar() {
		setLayout(new GridBagLayout());

		loadImages();
	}

	private void loadImages() {
		grip = loadImage("/resources/photos/title-grip.png");
		backgroundGradient = loadImage("/resources/photos/title-background.png");

		inactiveGrip = loadImage("/resources/photos/title-grip-inactive.png");
		inactiveBackgroundGradient = loadImage("/resources/photos/title-background-inactive.png");

		close = loadImage("/resources/photos/title-close.png");
		closeInactive = loadImage("/resources/photos/title-close-inactive.png");
		closeOver = loadImage("/resources/photos/title-close-over.png");
		closePressed = loadImage("/resources/photos/title-close-pressed.png");

		minimize = loadImage("/resources/photos/title-minimize.png");
		minimizeInactive = loadImage("/resources/photos/title-minimize-inactive.png");
		minimizeOver = loadImage("/resources/photos/title-minimize-over.png");
		minimizePressed = loadImage("/resources/photos/title-minimize-pressed.png");
	}

	private BufferedImage loadImage(String resourcePath) {
		java.net.URL imageurl = this.getClass().getResource(resourcePath);
		BufferedImage result = null;
		try {
			result = javax.imageio.ImageIO.read(imageurl);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	public void installListeners(Window window) {
		MouseInputHandler handler = new MouseInputHandler();

		window.addMouseListener(handler);
		window.addMouseMotionListener(handler);

		window.addWindowListener(new WindowHandler());
	}

	public void createButtons() {
		add(Box.createHorizontalGlue(), new GridBagConstraints(0, 0, 1, 1, 1.0,
				1.0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL,
				new Insets(0, 0, 0, 0), 0, 0));

		add(iconifyButton = createButton(new IconifyAction(), minimize,
				minimizePressed, minimizeOver), new GridBagConstraints(1, 0, 1,
				1, 0.0, 1.0, GridBagConstraints.NORTHEAST,
				GridBagConstraints.NONE, new Insets(1, 0, 0, 2), 0, 0));
		add(closeButton = createButton(new CloseAction(), close, closePressed,
				closeOver), new GridBagConstraints(2, 0, 1, 1, 0.0, 1.0,
				GridBagConstraints.NORTHEAST, GridBagConstraints.NONE,
				new Insets(1, 0, 0, 2), 0, 0));
	}

	private static JButton createButton(final AbstractAction action,
			final BufferedImage image, final Image pressedImage,
			final Image overImage) {
		JButton button = new JButton(action);
		button.setIcon(new ImageIcon(image));
		button.setPressedIcon(new ImageIcon(pressedImage));
		button.setRolloverIcon(new ImageIcon(overImage));
		button.setRolloverEnabled(true);
		button.setBorder(null);
		button.setBorderPainted(false);
		button.setContentAreaFilled(false);
		button.setMargin(new Insets(0, 0, 0, 0));
		button.setFocusable(false);
		button.setFocusPainted(false);
		button.setPreferredSize(new Dimension(image.getWidth(), image
				.getHeight()));
		return button;
	}

	private void close() {
		Window w = SwingUtilities.getWindowAncestor(this);
		w.dispatchEvent(new WindowEvent(w, WindowEvent.WINDOW_CLOSING));
	}

	private void iconify() {
		Frame frame = (Frame) SwingUtilities.getWindowAncestor(this);
		if (frame != null) {
			frame.setExtendedState(frame.getExtendedState() | Frame.ICONIFIED);
		}
	}

	@Override
	public Dimension getPreferredSize() {
		Dimension size = super.getPreferredSize();
		size.height = preferredHeight;

		return size;
	}

	@Override
	public Dimension getMinimumSize() {
		Dimension size = super.getMinimumSize();
		size.height = preferredHeight;

		return size;
	}

	@Override
	public Dimension getMaximumSize() {
		Dimension size = super.getMaximumSize();
		size.height = preferredHeight;
		return size;
	}

	@Override
	protected void paintComponent(Graphics g) {
		if (!isVisible()) {
			return;
		}
		
		/*JFrame parentFrame = (JFrame) super.getRootPane().getParent();
		parentFrame.setUndecorated(true);
		createButtons();
		installListeners(parentFrame);
		super.getRootPane().setJMenuBar(this);*/
		

		boolean active = SwingUtilities.getWindowAncestor(this).isActive();

		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_OFF);

		Rectangle clip = g2.getClipBounds();
		g2.drawImage(active ? backgroundGradient : inactiveBackgroundGradient,
				clip.x, 0, clip.width, getHeight() - 2, null);

		g2.setColor(active ? lightColor : inactiveLightColor);
		g2.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1);

		g2.setColor(active ? shadowColor : inactiveShadowColor);
		g2.drawLine(0, getHeight() - 2, getWidth(), getHeight() - 2);

		g2.drawImage(active ? grip : inactiveGrip, 0, 0, null);
	}

	private class CloseAction extends AbstractAction {
		/**
		 * 
		 */
		private static final long serialVersionUID = 5387368976552309687L;

		public void actionPerformed(ActionEvent e) {
			close();
		}
	}

	private class IconifyAction extends AbstractAction {
		/**
		 * 
		 */
		private static final long serialVersionUID = 990436616649045382L;

		public void actionPerformed(ActionEvent e) {
			iconify();
		}
	}

	private class MouseInputHandler implements MouseInputListener {
		private boolean isMovingWindow;
		private int dragOffsetX;
		private int dragOffsetY;

		private static final int BORDER_DRAG_THICKNESS = 5;

		public void mousePressed(MouseEvent ev) {
			Point dragWindowOffset = ev.getPoint();
			Window w = (Window) ev.getSource();
			if (w != null) {
				w.toFront();
			}
			Point convertedDragWindowOffset = SwingUtilities.convertPoint(w,
					dragWindowOffset, AerithTitleBar.this);

			Frame f = null;
			Dialog d = null;

			if (w instanceof Frame) {
				f = (Frame) w;
			} else if (w instanceof Dialog) {
				d = (Dialog) w;
			}

			int frameState = (f != null) ? f.getExtendedState() : 0;

			if (AerithTitleBar.this.contains(convertedDragWindowOffset)) {
				if ((f != null && ((frameState & Frame.MAXIMIZED_BOTH) == 0) || (d != null))
						&& dragWindowOffset.y >= BORDER_DRAG_THICKNESS
						&& dragWindowOffset.x >= BORDER_DRAG_THICKNESS
						&& dragWindowOffset.x < w.getWidth()
								- BORDER_DRAG_THICKNESS) {
					isMovingWindow = true;
					dragOffsetX = dragWindowOffset.x;
					dragOffsetY = dragWindowOffset.y;
				}
			} else if (f != null && f.isResizable()
					&& ((frameState & Frame.MAXIMIZED_BOTH) == 0)
					|| (d != null && d.isResizable())) {
				dragOffsetX = dragWindowOffset.x;
				dragOffsetY = dragWindowOffset.y;
			}
		}

		public void mouseReleased(MouseEvent ev) {
			isMovingWindow = false;
		}

		public void mouseDragged(MouseEvent ev) {
			Window w = (Window) ev.getSource();

			if (isMovingWindow) {
				Point windowPt = MouseInfo.getPointerInfo().getLocation();
				windowPt.x = windowPt.x - dragOffsetX;
				windowPt.y = windowPt.y - dragOffsetY;
				w.setLocation(windowPt);
			}
		}

		public void mouseClicked(MouseEvent e) {
		}

		public void mouseEntered(MouseEvent e) {
		}

		public void mouseExited(MouseEvent e) {
		}

		public void mouseMoved(MouseEvent e) {
		}
	}

	private class WindowHandler extends WindowAdapter {
		@Override
		public void windowActivated(WindowEvent ev) {
			closeButton.setIcon(new ImageIcon(close));
			iconifyButton.setIcon(new ImageIcon(minimize));
			getRootPane().repaint();
		}

		@Override
		public void windowDeactivated(WindowEvent ev) {
			closeButton.setIcon(new ImageIcon(closeInactive));
			iconifyButton.setIcon(new ImageIcon(minimizeInactive));
			getRootPane().repaint();
		}
	}
}
